package com.lsp.microarticle.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.lsp.microarticle.article.params.ArticleSearchParam;
import com.lsp.microarticle.article.service.EsArticleService;
import com.lsp.microarticle.article.vo.EsPage;
import com.lsp.microcommon.entity.Article;
import com.lsp.microcommon.exception.CommonException;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class EsArticleServiceImpl implements EsArticleService {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    // 向es中插入数据
    @Override
    public void addArticleInfo(Article article){

        IndexRequest indexRequest = new IndexRequest("qfedu-article");
        indexRequest.id(article.getId().toString()); // 文档id
        indexRequest.source(JSON.toJSONStringWithDateFormat(article, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat), XContentType.JSON);
        IndexResponse response = null;
        try {
            response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CommonException("添加article文档失败");
        }
        String status = response.status().toString();
        if (!("CREATED".equals(status) || "OK".equals(status))) {
            throw new CommonException("添加article文档失败");
        }
    }

    // 分页搜索es的数据
    @Override
    public EsPage<Article> searchArticle(ArticleSearchParam param) {
        SearchSourceBuilder builder = new SearchSourceBuilder();

        // 组合条件查
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should(QueryBuilders.matchQuery("title", param.getSearchInfo()));
        boolQueryBuilder.should(QueryBuilders.matchQuery("content", param.getSearchInfo()));
        builder.query(boolQueryBuilder);
        // 计算索引
        int index = (param.getPageNum() - 1) * param.getPageSize();
        builder.from(index);
        builder.size(param.getPageSize());
        // 排序
        builder.sort("createTime", SortOrder.DESC);
        // elasticsearch版本7.x如果查询的结果大于1w条，则在total上的总数只是返回1w，如果想要获取真实的总数
        // builder.trackTotalHits(true);
        // 设置索引
        SearchRequest searchRequest = new SearchRequest("qfedu-article");
        // 将sourceBulider放入searchRequest
        searchRequest.source(builder);

        List<Article> articles = new ArrayList<>();
        try {
            SearchResponse searchResp = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] searchHitArr = searchResp.getHits().getHits();
            // 总条数
            long totalHits = searchResp.getHits().getTotalHits().value;
            for (SearchHit searchHit : searchHitArr) {
                // 获取查询到的数据
                Map<String, Object> temp = searchHit.getSourceAsMap();
                Article info = new Article();
                info.setId(Integer.valueOf(searchHit.getId()));
                info.setTitle(temp.get("title").toString());
                info.setImgPath(temp.get("imgPath") == null ? "" : temp.get("imgPath").toString());
                articles.add(info);
            }
            return new EsPage(totalHits, articles);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
